/**
 有一个包子铺可以制作两种口味的包子，分别是肉馅和蔬菜馅。现在有一位包子铺师傅和三个顾客在排队等待买包子。要求：
 师傅可以无限制地制作包子；
 每个顾客只能买到一个包子；
 如果某个口味的包子售完了，需要等到师傅再次制作出来才能继续售卖；
 如何实现师傅和顾客之间的同步和通信？请编写代码实现。
 */
public class Test8 {
    public static void main(String[] args) {
        Shop shop = new Shop();

        // 创建包子师傅线程
        new Thread(new Chef(shop), "包子师傅").start();

        // 创建三个顾客线程
        new Thread(new Customer(shop, "肉馅"), "顾客1").start();
        new Thread(new Customer(shop, "蔬菜馅"), "顾客2").start();
        new Thread(new Customer(shop, "肉馅"), "顾客3").start();
    }
}

// 包子铺类，管理包子库存
class Shop {
    private int meatCount = 0;  // 肉馅包子数量
    private int vegetableCount = 0;  // 蔬菜馅包子数量

    // 制作肉馅包子
    public synchronized void makeMeatBaozi() {
        meatCount++;
        System.out.println("师傅制作了1个肉馅包子，当前肉馅库存: " + meatCount);
        notifyAll(); // 通知等待的顾客
    }

    // 制作蔬菜馅包子
    public synchronized void makeVegetableBaozi() {
        vegetableCount++;
        System.out.println("师傅制作了1个蔬菜馅包子，当前蔬菜馅库存: " + vegetableCount);
        notifyAll(); // 通知等待的顾客
    }

    // 购买肉馅包子
    public synchronized void buyMeatBaozi(String customer) throws InterruptedException {
        while (meatCount <= 0) {
            System.out.println(customer + " 想买肉馅包子，但是没有了，等待中...");
            wait();
        }
        meatCount--;
        System.out.println(customer + " 买到了1个肉馅包子，剩余肉馅: " + meatCount);
    }

    // 购买蔬菜馅包子
    public synchronized void buyVegetableBaozi(String customer) throws InterruptedException {
        while (vegetableCount <= 0) {
            System.out.println(customer + " 想买蔬菜馅包子，但是没有了，等待中...");
            wait();
        }
        vegetableCount--;
        System.out.println(customer + " 买到了1个蔬菜馅包子，剩余蔬菜馅: " + vegetableCount);
    }
}

// 包子师傅类
class Chef implements Runnable {
    private Shop shop;

    public Chef(Shop shop) {
        this.shop = shop;
    }

    @Override
    public void run() {
        System.out.println("包子师傅开始工作...");
        while (true) {
            try {
                // 交替制作两种包子
                Thread.sleep(1000);
                shop.makeMeatBaozi();

                Thread.sleep(1000);
                shop.makeVegetableBaozi();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

// 顾客类
class Customer implements Runnable {
    private Shop shop;
    private String preference;  // 偏好的包子口味

    public Customer(Shop shop, String preference) {
        this.shop = shop;
        this.preference = preference;
    }

    @Override
    public void run() {
        try {
            // 每个顾客只买一个包子
            if ("肉馅".equals(preference)) {
                shop.buyMeatBaozi(Thread.currentThread().getName());
            } else {
                shop.buyVegetableBaozi(Thread.currentThread().getName());
            }
            System.out.println(Thread.currentThread().getName() + " 买到了想要的包子，离开...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}